package zhouyang;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 可以先unpark再park，但是先unpark多次并不会累加许可证，许可证只可能为0或1.
 * 因此打开19行，先执行两个unpark，不管是一个线程执行的还是两个线程执行的，都不能打印t1被唤醒
 */
public class LockSupportDemo {
    static Object objectLock = new Object();
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
      Thread t1 =  new Thread(()->{
          try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            lock.lock();
             try {
                 System.out.println(Thread.currentThread().getName()+"\t"+"---come in");
                 LockSupport.park();
                 System.out.println("第一个park被唤醒后打印本行");
                 LockSupport.park();
                 System.out.println("第二个park被唤醒后打印本行");
                 System.out.println(Thread.currentThread().getName()+"\t"+"----被唤醒");
             }catch (Exception e) {
                 e.printStackTrace();
             }finally {
                 lock.unlock();
             }
        },"t1");
        t1.start();
//        TimeUnit.SECONDS.sleep(3);//打开19行不能打印出来t1被唤醒，关闭19行就可以打印
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"\t"+"---发出通知");
            LockSupport.unpark(t1);
            System.out.println("第一个unpark执行后");
            LockSupport.unpark(t1);//一个线程只能发一个许可证，超过的不起作用
            System.out.println("第二个unpark执行后");
        },"t2").start();

//        new Thread(()->{
//            LockSupport.unpark(t1);//如果要发2个许可证，可以多开一个线程，但是t1线程休眠3秒的话，不能打印t1被唤醒，证明许可证重复发放许可证值最大为1
//            System.out.println(Thread.currentThread().getName()+"\t"+"---发出通知");
//        },"t3").start();
    }

    private static void lockAwaitSignal() {
        new Thread(()->{
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+"\t"+"---come in");
                condition.await();
                System.out.println(Thread.currentThread().getName()+"\t"+"---被唤醒");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        },"t1").start();
        new Thread(()->{
            lock.lock();
            try {
                condition.signal();
            System.out.println(Thread.currentThread().getName()+"\t"+"---发出通知");
            } finally {
                lock.unlock();
            }
        },"t2").start();
    }

    private static void syncWaitNotify() {
        new Thread(()->{
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            synchronized (objectLock){
                System.out.println(Thread.currentThread().getName()+"\t"+"----come in");
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"\t"+"-----被唤醒");
            }
        },"t1").start();
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
        new  Thread(()->{
            synchronized (objectLock){
                objectLock.notify();
                System.out.println(Thread.currentThread().getName()+"\t"+"----发出通知");
            }
        },"t2").start();
    }
}
